﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace FindLargeFolderDotnet8AOT
{
    public class FindLargeFolder
    {
        public List<FolderInfo> FindLargeFolders(string path)
        {
            if (!Directory.Exists(path))
            {
                return new List<FolderInfo>();
            }
            List<FolderInfo> allFolderInfos = new List<FolderInfo>();
            List<FolderInfo> currentLevel = new List<FolderInfo>();
            int currentDepth = 0;
            currentLevel.Add(new FolderInfo()
            {
                path = path,
                depth = 0,
                size = 0,
                sizeAvailable=false
            });
            int found = 0;
            while (currentLevel.Count > 0)
            {
                allFolderInfos.AddRange(currentLevel);
                var nextLevel = new List<FolderInfo>();
                currentDepth += 1;
                foreach(FolderInfo currentFolder in currentLevel)
                {
                    DirectoryInfo directoryInfo = new DirectoryInfo(currentFolder.path);
                    try
                    {
                        foreach (DirectoryInfo subInfo in directoryInfo.EnumerateDirectories())
                        {
                            if (subInfo.LinkTarget != null)
                            {
                                continue;
                            }
                            nextLevel.Add(new FolderInfo()
                            {
                                path = subInfo.FullName,
                                depth = currentDepth,
                                size = 0,
                                sizeAvailable = false
                            });
                            Console.WriteLine(subInfo.FullName);
                            found += 1;
                            Console.WriteLine("找到"+found+"个文件夹");
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message + e.StackTrace);
                    }
                }
                currentLevel = nextLevel;
            }

            Console.WriteLine("一共找到:"+allFolderInfos.Count+"个文件夹,开始计算大小");
            Dictionary<string, FolderInfo> folderDict = new Dictionary<string, FolderInfo>();
            allFolderInfos = allFolderInfos.OrderByDescending(p => p.depth).ToList();
            foreach (FolderInfo folder in allFolderInfos)
            {
                folderDict.Add(folder.path, folder);
            }
            int calced = 0;
            foreach(FolderInfo folder in allFolderInfos)
            {
                CalcSize(folder, folderDict);
                calced += 1;
                Console.WriteLine("当前进度:" + calced + "/" + allFolderInfos.Count);
            }
            allFolderInfos = allFolderInfos.OrderByDescending(p => p.size).ToList();
            return allFolderInfos;
        }

        private long CalcSize(FolderInfo folderInfo,Dictionary<string, FolderInfo> folderDict)
        {
            if (folderInfo.sizeAvailable)
            {
                return folderInfo.size;
            }
            long size = 0;
            DirectoryInfo directoryInfo = new DirectoryInfo(folderInfo.path);
            try
            {
                foreach (DirectoryInfo subInfo in directoryInfo.EnumerateDirectories())
                {
                    if (subInfo.LinkTarget != null)
                    {
                        continue;
                    }
                    var path = subInfo.FullName;
                    var subFolderInfo = folderDict[path];
                    if (subFolderInfo.sizeAvailable)
                    {
                        size += subFolderInfo.size;
                    }
                    else
                    {
                        size += CalcSize(subFolderInfo, folderDict);
                    }
                }
                foreach (FileInfo fileInfo in directoryInfo.EnumerateFiles())
                {
                    size += fileInfo.Length;
                }
                folderInfo.size = size;
                folderInfo.sizeAvailable = true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message + e.StackTrace);
            }
            return size;
        }

        public string presentSize(long size)
        {
            if (size > 1024 * 1024 * 1024)
            {
                return String.Format("{0:F2}", Convert.ToDouble(size) / (1024d * 1024d * 1024d)) + "GB";
            }
            else if (size > 1024 * 1024)
            {
                return String.Format("{0:F2}", Convert.ToDouble(size) / (1024d * 1024d)) + "MB";
            }
            else if (size > 1024)
            {
                return String.Format("{0:F2}", Convert.ToDouble(size) / 1024d) + "KB";
            }
            else
            {
                return String.Format("{0:F2}", Convert.ToDouble(size)) + "bytes";
            }
        }
    }
}
